Skip to content

feat(ui): add StreamContextMenu and StreamContextMenuItem#53

Merged
xsahil03x merged 5 commits intomain-design-systemfrom
feat/context-menu
Feb 18, 2026
Merged

feat(ui): add StreamContextMenu and StreamContextMenuItem#53
xsahil03x merged 5 commits intomain-design-systemfrom
feat/context-menu

Conversation

@xsahil03x
Copy link
Member

@xsahil03x xsahil03x commented Feb 17, 2026

Screenshot 2026-02-17 at 22 42 18 image

Summary by CodeRabbit

  • New Features

    • Added a rich context menu component with separators and normal/destructive item variants, plus a builder hook for custom item renderers.
    • Exposed new theming APIs for context menus and items and wired them into the global theme system.
    • Added a platform override selector to the gallery toolbar to preview components on different target platforms.
    • Improved button styles with explicit icon size handling.
  • Documentation

    • Added comprehensive playground and showcase demos for the context menu in the design gallery.

- Add `PlatformSelector` component to switch between target platforms (Android, iOS, etc.).
- Update `PreviewConfiguration` to store and notify platform changes.
- Apply platform override in `PreviewWrapper` to ensure `StreamTheme` and `Theme` reflect the selected platform.
- Add the selector to the main `Toolbar`.
@xsahil03x xsahil03x requested a review from a team as a code owner February 17, 2026 17:12
@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Adds a new StreamContextMenu component and StreamContextMenuItem with full theming, integrates them into StreamTheme and component factory, exposes components in public exports, updates the design gallery with playground/showcase demos, and adds a platform override UI and plumbing in the gallery preview. Also refactors button theming to support icon sizing.

Changes

Cohort / File(s) Summary
Context Menu Components
packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu.dart, packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu_item.dart
Adds StreamContextMenu (with .separated factory) and StreamContextMenuSeparator, plus StreamContextMenuItem, StreamContextMenuItemProps, and DefaultStreamContextMenuItem. Includes private default style helpers for consistent theming and state handling.
Context Menu Theming
packages/stream_core_flutter/lib/src/theme/components/stream_context_menu_theme.dart, packages/stream_core_flutter/lib/src/theme/components/stream_context_menu_theme.g.theme.dart, packages/stream_core_flutter/lib/src/theme/components/stream_context_menu_item_theme.dart, packages/stream_core_flutter/lib/src/theme/components/stream_context_menu_item_theme.g.theme.dart
Introduces StreamContextMenuTheme and StreamContextMenuItemTheme APIs, data/style types, and generated helpers (lerp, copyWith, merge, ==, hashCode) for context menu container and item styling (colors, shapes, padding, overlays, icon sizes, etc.).
Theme System Integration
packages/stream_core_flutter/lib/src/theme/stream_theme.dart, packages/stream_core_flutter/lib/src/theme/stream_theme.g.theme.dart, packages/stream_core_flutter/lib/src/theme/stream_theme_extensions.dart, packages/stream_core_flutter/lib/src/theme.dart
Wires new context menu themes into StreamTheme (fields: contextMenuTheme, contextMenuItemTheme), updates constructors, copyWith, lerp, equality, hashCode, and adds extension getters for easy access.
Component Factory & Exports
packages/stream_core_flutter/lib/src/factory/stream_component_factory.dart, packages/stream_core_flutter/lib/src/factory/stream_component_factory.g.theme.dart, packages/stream_core_flutter/lib/src/components.dart
Adds contextMenuItem builder to StreamComponentBuilders (constructor, copy/merge/equality plumbing) and exports the new context menu component files from the components barrel.
Button Component Enhancement
packages/stream_core_flutter/lib/src/components/buttons/stream_button.dart, packages/stream_core_flutter/lib/src/theme/components/stream_button_theme.dart
Adds iconSize to StreamButtonThemeStyle, applies icon sizing to button styles, introduces _SharedButtonDefaults mixin for shared defaults (iconSize, overlayColor, elevation), and refactors default button style classes to use the mixin and public colorScheme.
Design Gallery Integration
apps/design_system_gallery/lib/app/gallery_app.directories.g.dart, apps/design_system_gallery/lib/components/context_menu/stream_context_menu.dart
Adds a Context Menu section to the gallery and a new gallery demo file with Playground and Showcase builders demonstrating many context menu variants and item states.
Preview Infrastructure & Toolbar
apps/design_system_gallery/lib/config/preview_configuration.dart, apps/design_system_gallery/lib/core/preview_wrapper.dart, apps/design_system_gallery/lib/widgets/toolbar/platform_selector.dart, apps/design_system_gallery/lib/widgets/toolbar/toolbar.dart
Adds a targetPlatform override to PreviewConfiguration with setter/getter and platformOptions; introduces _PlatformOverride wrapper in preview wrapper to reapply Material/Stream theme for a selected platform; adds PlatformSelector dropdown widget and integrates it into the toolbar.
Gallery manifest
pubspec.yaml
Minor manifest line changes (lines changed +24/-0) referenced in gallery updates.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Toolbar
  participant PreviewConfig
  participant PreviewWrapper
  participant StreamTheme

  User->>Toolbar: selects platform in PlatformSelector
  Toolbar->>PreviewConfig: setTargetPlatform(platform)
  PreviewConfig-->>Toolbar: notify listeners
  PreviewWrapper->>PreviewConfig: reads targetPlatform
  PreviewWrapper->>PreviewWrapper: wrap content with _PlatformOverride
  _PlatformOverride->>StreamTheme: applyPlatform(platform)
  StreamTheme-->>PreviewWrapper: themed content
  PreviewWrapper->>User: renders preview for selected platform
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐇 I hop to menus, neatly aligned,

themes tucked in corners, colors refined,
a dropdown of platforms, chosen with care,
icons that fit and items that pair,
I drum little paws—new components declare! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description contains only screenshots without any textual explanation of the changes, objectives, testing approach, or other required template sections. Add a comprehensive written description explaining what the PR accomplishes, how to test it, and fill in the CLA and code review checkboxes from the template.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main additions: StreamContextMenu and StreamContextMenuItem components are the core features introduced across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/context-menu

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xsahil03x
Copy link
Member Author

@coderabbitai review

@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 30.18868% with 148 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main-design-system@22dfc26). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...ponents/context_menu/stream_context_menu_item.dart 0.00% 58 Missing ⚠️
...c/components/context_menu/stream_context_menu.dart 2.56% 38 Missing ⚠️
...tream_core_flutter/lib/src/theme/stream_theme.dart 0.00% 19 Missing ⚠️
...eme/components/stream_context_menu_item_theme.dart 7.14% 13 Missing ⚠️
...rc/theme/components/stream_context_menu_theme.dart 7.14% 13 Missing ⚠️
...tter/lib/src/components/buttons/stream_button.dart 92.42% 5 Missing ⚠️
...flutter/lib/src/theme/stream_theme_extensions.dart 0.00% 2 Missing ⚠️

❌ Your patch status has failed because the patch coverage (30.18%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@                  Coverage Diff                  @@
##             main-design-system      #53   +/-   ##
=====================================================
  Coverage                      ?   35.22%           
=====================================================
  Files                         ?       95           
  Lines                         ?     2836           
  Branches                      ?        0           
=====================================================
  Hits                          ?      999           
  Misses                        ?     1837           
  Partials                      ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xsahil03x
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
packages/stream_core_flutter/lib/src/components/buttons/stream_button.dart (1)

376-647: Consider reducing boilerplate across the 9 default classes.

All 9 classes share identical structure: constructor capturing context, colorScheme, isFloating, with the mixin providing shared defaults. The only variance is in backgroundColor, foregroundColor, and borderColor. You could extract a common abstract base that handles the constructor boilerplate, with subclasses only overriding the color properties.

That said, the current approach is explicit and easy to follow — this is a low-priority suggestion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/stream_core_flutter/lib/src/components/buttons/stream_button.dart`
around lines 376 - 647, Multiple nearly-identical classes
(_PrimarySolidDefaults, _PrimaryOutlineDefaults, _PrimaryGhostDefaults,
_SecondarySolidDefaults, _SecondaryOutlineDefaults, _SecondaryGhostDefaults,
_DestructiveSolidDefaults, _DestructiveOutlineDefaults,
_DestructiveGhostDefaults) repeat constructor and fields; extract a single
abstract base (e.g., _BaseButtonDefaults extends StreamButtonThemeStyle with
_SharedButtonDefaults) that takes BuildContext and isFloating, assigns
colorScheme = context.streamColorScheme, and provides helper protected methods
for the common WidgetStateProperty.resolveWith patterns (e.g.,
resolveBackground(base), resolveForeground(defaultColor),
resolveBorder(defaultColor)); then make each specific class minimal by extending
_BaseButtonDefaults and only overriding
backgroundColor/foregroundColor/borderColor to call those helpers or supply
their differing base colors (e.g., colorScheme.accentPrimary,
colorScheme.backgroundSurface, colorScheme.accentError, isFloating logic, and
StreamColors.transparent) so the constructor/field boilerplate is removed from
each subclass.
packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu.dart (1)

192-215: Consider avoiding storing BuildContext in a field.

Storing BuildContext in _ContextMenuStyleDefaults works because it's created and consumed within a single build() call, but it's a pattern that Flutter lint rules sometimes flag. An alternative is to pass the resolved theme primitives directly. That said, this is a private class with a tightly scoped lifecycle, so the current approach is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu.dart`
around lines 192 - 215, Avoid storing BuildContext in _ContextMenuStyleDefaults:
change its constructor to accept the resolved theme primitives (StreamRadius,
StreamSpacing, StreamBoxShadow, StreamColorScheme) instead of BuildContext and
remove the context field; replace the late final fields (_radius, _spacing,
_boxShadow, _colorScheme) with constructor-assigned fields and update any
callers (where _ContextMenuStyleDefaults(...) is created inside build()) to
compute context.streamRadius, context.streamSpacing, context.streamBoxShadow and
context.streamColorScheme and pass them in.
packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu_item.dart (1)

219-227: MainAxisSize.min is a no-op when Expanded is present.

Expanded forces the Row to consume all available main-axis space, so MainAxisSize.min on Line 221 has no practical effect. This is functionally harmless (the parent TextButton provides bounded constraints), but it could mislead future readers into thinking the row shrinks to its content.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu_item.dart`
around lines 219 - 227, The Row sets mainAxisSize: MainAxisSize.min while also
wrapping props.label in Expanded, which makes mainAxisSize a no-op; remove the
misleading property (mainAxisSize: MainAxisSize.min) from the Row in
StreamContextMenuItem (the widget that builds the Row with ?props.leading,
Expanded(child: props.label), ?props.trailing) so the layout is clear, or
alternatively replace Expanded with Flexible if the intent is to allow the Row
to size to its content.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/design_system_gallery/lib/core/preview_wrapper.dart`:
- Around line 120-124: The overriddenStreamTheme construction discards
component-level customizations by only passing brightness, platform, and
colorScheme into the StreamTheme constructor; update the overridenStreamTheme
creation to forward all component theme properties from currentStreamTheme
(e.g., avatarTheme, badgeCountTheme, buttonTheme, contextMenuTheme,
contextMenuItemTheme, emojiButtonTheme, messageTheme, inputTheme,
onlineIndicatorTheme, onlineIndicatorTheme, etc.) while keeping brightness,
platform and colorScheme recalculated so existing per-component customizations
are preserved when platform-aware primitives (radius/typography) are recomputed.

In
`@packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu_item.dart`:
- Around line 279-287: The padding and shape getters use dot-shorthand on
abstract target types which resolves to nonexistent static members; in the
padding getter (WidgetStateProperty<EdgeInsetsGeometry> get padding) replace
`.symmetric(...)` with the concrete constructor EdgeInsets.symmetric(...), and
in the shape getter (WidgetStateProperty<OutlinedBorder> get shape) replace
`.all(...)` with the concrete BorderRadius.all(...), keeping the surrounding
WidgetStatePropertyAll and RoundedRectangleBorder usage intact so the types
resolve correctly.

In
`@packages/stream_core_flutter/lib/src/theme/components/stream_context_menu_theme.g.theme.dart`:
- Around line 154-186: The equality and hashCode for StreamContextMenuStyle use
list identity for boxShadow (in operator== and hashCode), causing incorrect
comparisons; update the generated code in ThemeGenGenerator so operator==
compares lists with listEquals(_other.boxShadow, _this.boxShadow) (importing
package:flutter/foundation.dart) and change the hashCode to include a deep hash
for the list (e.g., Object.hashAll(_this.boxShadow) or similar) instead of
hashing the list object itself; ensure references to backgroundColor, shape,
side, boxShadow, padding remain and only the boxShadow comparison/hash logic is
adjusted.

---

Nitpick comments:
In `@packages/stream_core_flutter/lib/src/components/buttons/stream_button.dart`:
- Around line 376-647: Multiple nearly-identical classes (_PrimarySolidDefaults,
_PrimaryOutlineDefaults, _PrimaryGhostDefaults, _SecondarySolidDefaults,
_SecondaryOutlineDefaults, _SecondaryGhostDefaults, _DestructiveSolidDefaults,
_DestructiveOutlineDefaults, _DestructiveGhostDefaults) repeat constructor and
fields; extract a single abstract base (e.g., _BaseButtonDefaults extends
StreamButtonThemeStyle with _SharedButtonDefaults) that takes BuildContext and
isFloating, assigns colorScheme = context.streamColorScheme, and provides helper
protected methods for the common WidgetStateProperty.resolveWith patterns (e.g.,
resolveBackground(base), resolveForeground(defaultColor),
resolveBorder(defaultColor)); then make each specific class minimal by extending
_BaseButtonDefaults and only overriding
backgroundColor/foregroundColor/borderColor to call those helpers or supply
their differing base colors (e.g., colorScheme.accentPrimary,
colorScheme.backgroundSurface, colorScheme.accentError, isFloating logic, and
StreamColors.transparent) so the constructor/field boilerplate is removed from
each subclass.

In
`@packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu_item.dart`:
- Around line 219-227: The Row sets mainAxisSize: MainAxisSize.min while also
wrapping props.label in Expanded, which makes mainAxisSize a no-op; remove the
misleading property (mainAxisSize: MainAxisSize.min) from the Row in
StreamContextMenuItem (the widget that builds the Row with ?props.leading,
Expanded(child: props.label), ?props.trailing) so the layout is clear, or
alternatively replace Expanded with Flexible if the intent is to allow the Row
to size to its content.

In
`@packages/stream_core_flutter/lib/src/components/context_menu/stream_context_menu.dart`:
- Around line 192-215: Avoid storing BuildContext in _ContextMenuStyleDefaults:
change its constructor to accept the resolved theme primitives (StreamRadius,
StreamSpacing, StreamBoxShadow, StreamColorScheme) instead of BuildContext and
remove the context field; replace the late final fields (_radius, _spacing,
_boxShadow, _colorScheme) with constructor-assigned fields and update any
callers (where _ContextMenuStyleDefaults(...) is created inside build()) to
compute context.streamRadius, context.streamSpacing, context.streamBoxShadow and
context.streamColorScheme and pass them in.

@xsahil03x
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/design_system_gallery/lib/core/preview_wrapper.dart`:
- Around line 98-122: The _PlatformOverride build currently replaces the prior
broken logic by using streamTheme.applyPlatform(platform); ensure this stays and
modify the extensions argument to pass a List combining existing extensions with
the platform-applied StreamTheme (e.g., use [...theme.extensions.values,
streamTheme.applyPlatform(platform)]) so ThemeData.copyWith(extensions: ...)
receives the correct ordered collection and the StreamTheme from
streamTheme.applyPlatform(platform) overrides the existing StreamTheme; key
symbols: _PlatformOverride, streamTheme, applyPlatform,
ThemeData.copyWith(extensions:).

@xsahil03x xsahil03x merged commit 0d06cf5 into main-design-system Feb 18, 2026
3 of 4 checks passed
@xsahil03x xsahil03x deleted the feat/context-menu branch February 18, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants